package com.dyna.controller;

import com.dyna.constants.ModuleErrorCodeConstants;
import com.dyna.core.utils.CollUtil;
import com.dyna.domain.dto.LoginUser;
import com.dyna.domain.req.PageParam;
import com.dyna.domain.resp.PageResult;
import com.dyna.domain.resp.R;
import com.dyna.domain.resp.ResultCode;
import com.dyna.enums.CommonStatusEnum;
import com.dyna.enums.SexEnum;
import com.dyna.excel.core.util.ExcelUtil;
import com.dyna.foundation.convert.UserConvert;
import com.dyna.foundation.domain.bo.UserInfoBo;
import com.dyna.foundation.domain.entity.SysDept;
import com.dyna.foundation.domain.entity.SysUser;
import com.dyna.foundation.domain.form.SysUserSaveForm;
import com.dyna.foundation.domain.req.SysUserPageReq;
import com.dyna.foundation.domain.req.UserUpdatePasswordReq;
import com.dyna.foundation.domain.req.UserUpdateStatusReq;
import com.dyna.foundation.domain.resp.SysUserImportExcelResp;
import com.dyna.foundation.domain.resp.SysUserImportResp;
import com.dyna.foundation.domain.resp.SysUserResp;
import com.dyna.foundation.domain.resp.UserSimpleResp;
import com.dyna.foundation.feign.FoundationUserApi;
import com.dyna.service.SysDeptService;
import com.dyna.service.SysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * @description 用户模块
 * @author zhoucaiwnag
 * @date 2023-08-13
 */

@Api(value = "用户")
@RestController
@Validated
@AllArgsConstructor
@RequestMapping(value = "/user")
public class SysUserController implements FoundationUserApi {

    private SysUserService userService;
    private SysDeptService deptService;

    @PostMapping("/create")
    @ApiOperation(value = "新增用户")
    public R<Long> createUser(@Valid @RequestBody SysUserSaveForm reqVO) {
        Long id = userService.createUser(reqVO);
        return R.data(id);
    }

    @PutMapping("/update")
    @ApiOperation(value = "修改用户")
    public R<Boolean> updateUser(@Valid @RequestBody SysUserSaveForm reqVO) {
        userService.updateUser(reqVO);
        return R.data(true);
    }

    @DeleteMapping("/delete")
    @ApiOperation(value = "删除用户")
    @ApiImplicitParams(value = {@ApiImplicitParam(name = "userId", value = "编号", required = true, example = "1024")})
    public R<Boolean> deleteUser(@RequestParam("userId") Long userId) {
        userService.deleteUser(userId);
        return R.data(true);
    }

    @PutMapping("/update-password")
    @ApiOperation(value = "重置用户密码")
    public R<Boolean> updateUserPassword(@Valid @RequestBody UserUpdatePasswordReq reqVO) {
        userService.updateUserPassword(reqVO.getUserId(), reqVO.getPassword());
        return R.data(true);
    }

    @PutMapping("/update-status")
    @ApiOperation(value = "修改用户状态")
    public R<Boolean> updateUserStatus(@Valid @RequestBody UserUpdateStatusReq reqVO) {
        userService.updateUserStatus(reqVO.getUserId(), reqVO.getStatus());
        return R.data(true);
    }

    @GetMapping("/page")
    @ApiOperation(value = "获得用户分页列表")
    public R<PageResult<SysUserResp>> getUserPage(@Valid SysUserPageReq pageReqVO) {
        // 获得用户分页列表
        PageResult<SysUser> pageResult = userService.getUserPage(pageReqVO);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return R.data(new PageResult<>(pageResult.getTotal()));
        }
        // 拼接数据
        Map<Long, SysDept> deptMap = deptService.getDeptMap(CollUtil.convertList(pageResult.getList(), SysUser::getDeptId));
        List<SysUserResp> userRespList = UserConvert.convertList(pageResult.getList(), deptMap);
        return R.data(new PageResult<>(userRespList, pageResult.getTotal()));
    }

    @GetMapping({"/list-all-simple", "/simple-list"})
    @ApiOperation(value = "获取用户精简信息列表", notes = "只包含被开启的用户，主要用于前端的下拉选项")
    public R<List<UserSimpleResp>> getSimpleUserList() {
        List<SysUser> list = userService.getUserListByStatus(CommonStatusEnum.ENABLE.getStatus());
        // 拼接数据
        Map<Long, SysDept> deptMap = deptService.getDeptMap(
                CollUtil.convertList(list, SysUser::getDeptId));
        return R.data(UserConvert.convertSimpleList(list, deptMap));
    }

    @Override
    @GetMapping("/get")
    @ApiOperation(value = "获得用户详情")
    @ApiImplicitParams(value = {@ApiImplicitParam(name = "userId", value = "编号", required = true, example = "1024")})
    public R<SysUserResp> getUser(@RequestParam("userId") Long userId) {
        SysUser user = userService.getUser(userId);
        if (user == null) {
            return R.success(ResultCode.SUCCESS, ModuleErrorCodeConstants.USER_NOT_EXISTS.getMsg());
        }
        // 拼接数据
        SysDept dept = deptService.getDept(user.getDeptId());
        return R.data(UserConvert.convert(user, dept));
    }

    @GetMapping("/export")
    @ApiOperation(value = "导出用户")
    public void exportUserList(@Validated SysUserPageReq exportReqVO,
                               HttpServletResponse response) throws IOException {
        exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<SysUser> list = userService.getUserPage(exportReqVO).getList();
        // 输出 Excel
        Map<Long, SysDept> deptMap = deptService.getDeptMap(CollUtil.convertList(list, SysUser::getDeptId));
        ExcelUtil.write(response, "用户数据.xls", "数据", SysUserResp.class,
                UserConvert.convertList(list, deptMap));
    }

    @GetMapping("/get-import-template")
    @ApiOperation(value = "获得导入用户模板")
    public void importTemplate(HttpServletResponse response) throws IOException {
        // 手动创建导出 demo
        List<SysUserImportExcelResp> list = Arrays.asList(
                SysUserImportExcelResp.builder().username("yunai").deptId(1L).email("yunai@iocoder.cn").mobile("15601691300")
                        .nickname("芋道").status(CommonStatusEnum.ENABLE.getStatus()).sex(SexEnum.MALE.getSex()).build(),
                SysUserImportExcelResp.builder().username("yuanma").deptId(2L).email("yuanma@iocoder.cn").mobile("15601701300")
                        .nickname("源码").status(CommonStatusEnum.DISABLE.getStatus()).sex(SexEnum.FEMALE.getSex()).build()
        );
        // 输出
        ExcelUtil.write(response, "用户导入模板.xls", "用户列表", SysUserImportExcelResp.class, list);
    }

    @PostMapping("/import")
    @ApiOperation(value = "导入用户")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "Excel 文件", required = true),
            @ApiImplicitParam(name = "updateSupport", value = "是否支持更新，默认为 false", example = "true")
    })
    public R<SysUserImportResp> importExcel(@RequestParam("file") MultipartFile file,
                                            @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception {
        List<SysUserImportExcelResp> list = ExcelUtil.read(file, SysUserImportExcelResp.class);
        return R.data(userService.importUserList(list, updateSupport));
    }

    /** ----------------------------------------------------------------------------------- **/

    @Override
    @ApiOperation(value = "查询登录用户")
    @RequestMapping("/getLoginUserById")
    public R<LoginUser> getLoginUserById(@RequestParam(value = "userId") @NotNull(message = "用户id不能为空") Long userId) {
        return R.data(userService.getLoginUserById(userId));
    }

    @ApiOperation(value = "批量查询用户")
    @RequestMapping("/getUserByIds")
    public R<List<UserInfoBo>> getUserByIds(@RequestBody List<Long> userIdList) {
        List<UserInfoBo> userInfoBoList = userService.getUserByIds(userIdList);
        return R.data(userInfoBoList);
    }

    @Override
    @ApiOperation(value = "根据用户名查询")
    @RequestMapping("/getUserByUsername/{username}")
    public R<SysUser> getUserByUsername(@PathVariable("username") String username) {
        return R.data(userService.getUserByUsername(username));
    }

    @ApiOperation(value = "用户签到")
    @GetMapping("/sign")
    public R<Long> sign() {
        return R.data(userService.sign());
    }

    @ApiOperation(value = "取消用户签到")
    @GetMapping("/cancel/sign")
    public R<Boolean> cancelSign() {
        return R.data(userService.cancelSign());
    }

    @ApiOperation("根据角色id查询")
    @GetMapping("/getUserByRoleId")
    public R<List<UserInfoBo>> getUserByRoleId(@RequestParam("roleId") Long roleId) {
        List<UserInfoBo> userInfoBoList = userService.getUserByRoleId(roleId);
        return R.data(userInfoBoList);
    }

    @ApiOperation(value = "测试远程刪除用户调用异常结果")
    @RequestMapping("/testDel")
    public R<Boolean> testDel(@RequestParam("userId") Long userId){
        return R.data(userService.testDel(userId));
    }

}

